package com.yxinsur.imc.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxinsur.imc.business.domain.ImcContract;
import com.yxinsur.imc.business.domain.ImcContractFile;
import com.yxinsur.imc.business.domain.ImcContractIns;
import com.yxinsur.imc.business.domain.ImcContractOrg;
import com.yxinsur.imc.business.enums.IsDeletedEnum;
import com.yxinsur.imc.business.form.ContractForm;
import com.yxinsur.imc.business.mapper.*;
import com.yxinsur.imc.business.service.IImcContractFileService;
import com.yxinsur.imc.business.service.IImcContractService;
import com.yxinsur.imc.business.vo.ContractOrgVo;
import com.yxinsur.imc.business.vo.ContractVo;
import com.yxinsur.imc.business.vo.ImcContractExpenseVo;
import com.yxinsur.imc.business.vo.RepoInsVo;
import com.yxinsur.imc.common.core.domain.AjaxResult;
import com.yxinsur.imc.common.utils.DateUtils;
import com.yxinsur.imc.common.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 合同Service业务层处理
 *
 * @author imc
 * @date 2021-04-22
 */
@Service
public class ImcContractServiceImpl extends ServiceImpl<ImcContractMapper, ImcContract> implements IImcContractService {
    private static final Logger logger = LoggerFactory.getLogger(ImcContractServiceImpl.class);

    @Autowired
    private ImcContractMapper imcContractMapper;
    @Autowired
    private ImcContractInsMapper imcContractInsMapper;
    @Autowired
    private ImcContractOrgMapper imcContractOrgMapper;
    @Autowired
    private ImcRepoInsMapper imcRepoInsMapper;
    @Autowired
    private ImcContractFileMapper imcContractFileMapper;
    @Autowired
    private ImcRecnDetailsMapper imcRecnDetailsMapper;
    @Autowired
    private ImcRenewalRecnMapper imcRenewalRecnMapper;
    @Autowired
    private ImcContractExpenseMapper imcContractExpenseMapper;
    @Autowired
    private IImcContractFileService imcContractFileService;

    /**
     * 协议管理-查询列表
     *
     * @param contractForm 协议
     * @return List<ContractVo>
     */
    @Override
    public List<ContractVo> selectImcContractList(ContractForm contractForm) {
        logger.info("合同列表查询，条件：{}", contractForm.toString());

        List<ContractVo> contractVos = imcContractMapper.selectImcContractList(contractForm, SecurityUtils.getTenantId());
        for (ContractVo contractVo : contractVos) {
            ImcContractIns imcContractIns = new ImcContractIns();
            imcContractIns.setContractId(contractVo.getId());
            List<ImcContractIns> insList = imcContractInsMapper.selectImcContractInsList(imcContractIns);
            ArrayList<RepoInsVo> repoInsVos = new ArrayList<>();
            for (ImcContractIns ins : insList) {
                RepoInsVo imcRepoInsById = imcRepoInsMapper.getImcRepoInsById(ins.getRepoInsId());
                repoInsVos.add(imcRepoInsById);
            }
            contractVo.setRepoInsVoList(repoInsVos);
            List<ContractOrgVo> contractOrgVoList = imcContractOrgMapper.selectImcContractOrgByContractId(contractVo.getId());
            contractVo.setContractOrgVoList(contractOrgVoList);
            contractVo.setContractOrg(contractOrgVoList.stream().map(ContractOrgVo::getOrgName).collect(Collectors.toList()).toString());
            List<ImcContractFile> contractFiles = imcContractFileMapper.selectByContractId(contractVo.getId());
            contractVo.setContractUrl(contractFiles.stream().map(ImcContractFile::getFileUrl).collect(Collectors.toList()).toString());
        }
        return contractVos;
    }

    /**
     * 查询主协议
     *
     * @param id             当前协议ID
     * @param repoSupplierId 供应商ID
     * @return List<ContractVo>
     */
    @Override
    public List<ContractVo> listMasterContract(Long id, Long repoSupplierId) {
        return imcContractMapper.listMasterContract(id, repoSupplierId, SecurityUtils.getTenantId());
    }

    /**
     * 协议管理-新增协议
     *
     * @param contractForm 协议
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertImcContract(ContractForm contractForm) {
        logger.info("新增协议操作，条件：{}", contractForm.toString());

        String username = SecurityUtils.getUsername();
        Long tenantId = SecurityUtils.getTenantId();

        boolean isExistContract = this.imcContractMapper.countOfImcContractByName(contractForm.getContractName(), contractForm.getRepoSupplierId(), tenantId) > 0;
        if (isExistContract) {
            return AjaxResult.error("该供应商下已存在此协议，不可重复添加");
        }

        // 保存协议基础信息
        ImcContract contract = new ImcContract();
        BeanUtils.copyProperties(contractForm, contract);
        contract.setCreateTime(DateUtils.getNowDate());
        contract.setCreateId(username);
        contract.setIsDeleted(IsDeletedEnum.N.getCode());
        contract.setTenantId(tenantId);
        this.imcContractMapper.insert(contract);

        // 保存协议-产品关系
        Long[] insIds = contractForm.getInsIds();
        for (Long insId : insIds) {
            ImcContractIns imcContractIns = new ImcContractIns();
            imcContractIns.setContractId(contract.getId());
            imcContractIns.setRepoInsId(insId);
            imcContractIns.setCreateId(username);
            imcContractIns.setCreateTime(DateUtils.getNowDate());
            imcContractIns.setTenantId(tenantId);
            imcContractInsMapper.insertImcContractIns(imcContractIns);
        }

        // 保存协议-签约机构关系
        Long[] orgIds = contractForm.getOrgIds();
        for (Long orgId : orgIds) {
            ImcContractOrg imcContractOrg = new ImcContractOrg();
            imcContractOrg.setContractId(contract.getId());
            imcContractOrg.setOrgId(orgId);
            imcContractOrg.setTenantId(tenantId);
            imcContractOrg.setCreateId(username);
            imcContractOrg.setCreateTime(DateUtils.getNowDate());
            imcContractOrg.setUpdateId(username);
            imcContractOrg.setUpdateTime(DateUtils.getNowDate());
            imcContractOrgMapper.insertImcContractOrg(imcContractOrg);
        }

        // 保存协议-上传文件关系
        imcContractFileService.saveNewFile(contract.getId(), contractForm.getContractFiles());
        return AjaxResult.success();
    }

    /**
     * 修改协议
     *
     * @param contractForm 协议
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateImcContract(ContractForm contractForm) {
        logger.info("合同更新操作，条件：{}", contractForm.toString());

        String username = SecurityUtils.getUsername();
        Long tenantId = SecurityUtils.getTenantId();

        ImcContract contract = this.imcContractMapper.selectById(contractForm.getId());

        if (!contract.getContractName().equals(contractForm.getContractName())) {
            boolean isExistContract = this.imcContractMapper.countOfImcContractByName(contractForm.getContractName(), contractForm.getRepoSupplierId(), tenantId) > 0;
            if (isExistContract) {
                return AjaxResult.error("该供应商下已存在此协议，不可重复添加");
            }
        }

        // 修改协议基础信息（当协议由附属协议=>主协议，应清空所属主协议字段）
        boolean isMaster = contract.getIsMaster() == 0 && contractForm.getIsMaster() == 1;
        BeanUtils.copyProperties(contractForm, contract);
        if (isMaster) {
            contract.setMasterContractId(null);
        }
        contract.setUpdateTime(DateUtils.getNowDate());
        contract.setUpdateId(SecurityUtils.getUsername());
        imcContractMapper.updateImcContract(contract);

        // 修改协议-上传文件关系（删除旧文件、保存新文件）
        imcContractFileService.saveNewFile(contractForm.getId(), contractForm.getContractFiles());

        // 修改协议-产品关系
        Long[] insIds = contractForm.getInsIds();
        imcContractInsMapper.deleteByContractId(contract.getId());
        for (Long insId : insIds) {
            ImcContractIns imcContractIns = new ImcContractIns();
            imcContractIns.setContractId(contract.getId());
            imcContractIns.setRepoInsId(insId);
            imcContractIns.setCreateId(username);
            imcContractIns.setCreateTime(DateUtils.getNowDate());
            imcContractIns.setTenantId(tenantId);
            imcContractInsMapper.insertImcContractIns(imcContractIns);
        }

        // 修改协议-签约机构关系
        Long[] orgIds = contractForm.getOrgIds();
        imcContractOrgMapper.deleteByContractId(contract.getId());
        for (Long orgId : orgIds) {
            ImcContractOrg imcContractOrg = new ImcContractOrg();
            imcContractOrg.setContractId(contract.getId());
            imcContractOrg.setOrgId(orgId);
            imcContractOrg.setTenantId(tenantId);
            imcContractOrg.setCreateId(username);
            imcContractOrg.setCreateTime(DateUtils.getNowDate());
            imcContractOrg.setUpdateId(username);
            imcContractOrg.setUpdateTime(DateUtils.getNowDate());
            imcContractOrgMapper.insertImcContractOrg(imcContractOrg);
        }
        return AjaxResult.success();
    }

    /**
     * 删除协议
     *
     * @param id 协议ID
     * @return 结果
     */
    @Override
    public AjaxResult deleteImcContractById(Long id) {
        List<ImcContractExpenseVo> imcContractExpenseVoList = this.imcContractExpenseMapper.listImcContractExpenseByContractId(id, SecurityUtils.getTenantId());
        if (ObjectUtil.isNotNull(imcContractExpenseVoList)) {
            for (ImcContractExpenseVo item : imcContractExpenseVoList) {
                boolean usedOfRecn = this.imcRecnDetailsMapper.countOfRecnByContractExpenseId(item.getId(), SecurityUtils.getTenantId()) > 0;
                if (usedOfRecn) {
                    return AjaxResult.error("协议已经被首期手续费对账单使用，无法删除");
                }
                boolean usedOfRenewalRecn = this.imcRenewalRecnMapper.countOfRenewalRecnByContractExpenseId(item.getId(), SecurityUtils.getTenantId()) > 0;
                if (usedOfRenewalRecn) {
                    return AjaxResult.error("协议已经被续期手续费对账单使用，无法删除");
                }
            }
        }
        ImcContract contract = this.imcContractMapper.selectById(id);
        contract.setIsDeleted(id.toString());
        contract.setUpdateId(SecurityUtils.getUsername());
        contract.setUpdateTime(DateUtils.getNowDate());
        this.imcContractMapper.updateById(contract);
        return AjaxResult.success();
    }

    /**
     * 协议管理-查询详情
     *
     * @param id 协议id
     * @return ContractVo
     */
    @Override
    public ContractVo selectImcContractById(Long id) {
        ContractVo contract = imcContractMapper.getImcContractById(id);
        ImcContractIns imcContractIns = new ImcContractIns();
        imcContractIns.setContractId(id);
        List<ImcContractIns> insList = imcContractInsMapper.selectImcContractInsList(imcContractIns);
        // 产品险种信息
        List<RepoInsVo> repoInsVos = new ArrayList<>();
        for (ImcContractIns contractIns : insList) {
            RepoInsVo repoInsVo = imcRepoInsMapper.getImcRepoInsById(contractIns.getRepoInsId());
            repoInsVos.add(repoInsVo);
        }
        contract.setRepoInsVoList(repoInsVos);
        List<ContractOrgVo> contractOrgVoList = imcContractOrgMapper.selectImcContractOrgByContractId(id);
        contract.setContractOrgVoList(contractOrgVoList);
        List<ImcContractFile> contractFiles = imcContractFileMapper.selectByContractId(id);
        contract.setContractFiles(contractFiles);
        return contract;
    }
}
